package ooo.reindeer.commons.utils.limit;

import java.io.IOException;
import java.util.Timer;
import java.util.TimerTask;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicLong;

public class SpeedLimit implements ISpeedLimit {
	private final Timer m_time=new Timer();
	private final AtomicLong m_seed=new AtomicLong();
	private final AtomicBoolean unlimited =new AtomicBoolean(false);

	private final AtomicBoolean zoom=new AtomicBoolean(false);


	@Override
	public void shutdown() {
		m_time.cancel();
	}

	@Override
	public long getMaxSpeed() {
        return m_max_speed.get();
    }

	@Override
	public long getCycle() {
		return m_cycle.get();
	}



    private final AtomicLong m_max_speed=new AtomicLong();
	private final AtomicLong m_cycle=new AtomicLong();
	private TimerTask m_task;

	@Override
	public void setMaxSpeed(long speed){

		m_max_speed.set(zoom.get()?speed*10:speed);
	}

	@Override
	public void setCycle(long cycle){

		m_cycle.set(zoom.get()?cycle*10:cycle);
	}

	@Override
	public void setLimit(long speed, long cycle){
		m_max_speed.set(zoom.get()?speed*10:speed);
		m_cycle.set(zoom.get()?cycle*10:cycle);
	}

	
	public SpeedLimit(long speed,long cycle){
		zoom.set(cycle<10);

		m_max_speed.set(zoom.get()?speed*10:speed);
		m_cycle.set(zoom.get()?cycle*10:cycle);

		m_task= getRestorer();

		m_time.scheduleAtFixedRate(m_task, 0, m_cycle.get());
		
	}
	
	@Override
	public void blockLimit(){

		while(checkLimit()){
		
			synchronized (m_seed) {
				try {
					
					m_seed.wait();
					
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
			}

		}

	}

	@Override
	public boolean checkLimit(){

		return (!(m_max_speed.get() < 1 || unlimited.get())) && m_seed.decrementAndGet() < 0;
	}

	@Override
	public void resume(){
		if(unlimited.compareAndSet(true,false)){
			m_time.schedule(m_task, 0, m_cycle.get());
		}
	}
	
	@Override
	public void cancel(){
		if(unlimited.compareAndSet(false,true)) {
			synchronized (m_seed) {
				m_seed.notifyAll();
			}
			m_task.cancel();
			m_task= getRestorer();

		}
	}

	@Override
	public TimerTask getRestorer(){
		return new Restorer();
	}

	private class Restorer extends TimerTask {

		long cycle=-1;

		@Override
		public void run() {
			m_seed.set(m_max_speed.get());
			synchronized (m_seed) {
				m_seed.notifyAll();
			}
			if(cycle!=m_cycle.get()) {
				if(cycle!=-1) {
					m_task.cancel();
					m_task= getRestorer();
					m_time.scheduleAtFixedRate(m_task, m_cycle.get(), m_cycle.get());
				}
				cycle=m_cycle.get();
			}
		}
	}


	public static void main(String[] args) throws IOException {
		ISpeedLimit sl=new SpeedLimit(11, 1000);
		for(int i=0;i<100;i++){
			sl.blockLimit();
			System.out.println(i);
			if(i==50){
				sl.setMaxSpeed(2);
				sl.setCycle(2000);
			}
		}
		sl.shutdown();
	}
}